home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_074 / makemake / makemake.c < prev   
C/C++ Source or Header  |  1992-05-06  |  7KB  |  256 lines

  1. /*
  2.  *
  3.  * MakeMake - a program to construct a makefile from C source code
  4.  *
  5.  *   Usage: makemake file1.c file2.c file3.c ... filen.c
  6.  *
  7.  * MakeMake reads the C source files and creates
  8.  * a file called 'makefile' in the current directory. For each
  9.  * source file entered on the command line, makemake adds an entry 
  10.  * of the form:
  11.  * 
  12.  *   filex.o :    filex.c ... header file list ...
  13.  *       cc $(OPT) filex.c
  14.  * 
  15.  * where the header file list is the transitive closure of all
  16.  * files #included in filex.c (i.e. if filex.c #includes "header.h", and
  17.  * "header.h" #includes "subheader.h", both "header.h" and "subheader.h"
  18.  * appear in the list of header files). MakeMake only examines header
  19.  * files delimited by double quotes ("). System header files enclosed
  20.  * in angle brackets (< and >) are not examined.
  21.  * 
  22.  * The target of the makefile is assumed to be a program called 'main', 
  23.  * with dependencies as shown:
  24.  * 
  25.  * main :  file1.o file2.o file3.o ... filek.o
  26.  * main :  filek+1.o ... filen.o
  27.  * # ------- construction command goes here ---------
  28.  * 
  29.  * At this point, the programmer should edit the resulting makefile
  30.  * to add the statement sequence which builds the program from the 
  31.  * compiled object code by replacing the '#' comment line.
  32.  * 
  33.  * The makefile has a hook for specifying compilation options through
  34.  * symbol OPT. 
  35.  * 
  36.  * Written and placed in the public domain by Tim McGrath 4/2/87
  37.  * 
  38.  */
  39. #include <stdio.h>
  40. #define LINEMAX 80
  41. #define MAINPGM "main"
  42.  
  43. long malloc();
  44. char *strcat(),*strcpy();
  45.  
  46. FILE *makefile;
  47.  
  48. main(argc,argv)
  49.     char **argv; 
  50.     int argc;
  51.   int dependent_count;
  52.   char **dependents;
  53.   int i;
  54.   
  55.   if ((makefile = fopen("makefile","w")) == 0L) {
  56.     puts("Can't create makefile"); exit(1);
  57.   }
  58.   fprintf(makefile,"OPT = \n\n");
  59.   depend_file(argc,argv,MAINPGM,"  ",".o");
  60.   for (i = 1; i < argc; i++) {
  61.     get_dependents(argv[i],&dependents,&dependent_count);
  62.     depend_file(dependent_count,dependents,argv[i],".o","");
  63.     free_space(dependents,dependent_count);
  64.   }
  65.   fclose(makefile); exit(0);
  66. }
  67.  
  68. free_space(dp,dc)
  69. /* 
  70.  * Purpose: free up list of file names
  71.  * Inputs:  dp - points to list of pointers to strings
  72.  *        dc - number of pointers in the list
  73.  */
  74.     char **dp;
  75.     int dc;
  76. {
  77.   while (dc > 0) {
  78.     free(*dp++); dc--;
  79.   }
  80.   free(dp);
  81. }
  82.  
  83. char *
  84. file_exten(pgm_name,xtension,bufout)
  85. /* 
  86.  * Purpose: append new extension onto file name 
  87.  * Inputs:  pgm_name - pointer to name of file
  88.  *        xtension - pointer to new file name extension (2 chars only)
  89.  * Outputs: bufout - points to area for new file name
  90.  * Returns: bufout
  91.  */
  92.      char *pgm_name,*xtension,*bufout;
  93. {
  94.   int i = 0;
  95.   
  96.   while (*pgm_name) {
  97.     bufout[i++] = *pgm_name;
  98.     if (*pgm_name++ == '.' && xtension[0] != '\0') {
  99.       bufout[i++] = xtension[1]; 
  100.       break;
  101.     }
  102.   }
  103.   bufout[i] = '\0'; return(bufout);
  104. }
  105.  
  106. depend_file(ct,flist,pgm_name,pgmx,filex)
  107. /* 
  108.  * Purpose: print file name and list of dependents
  109.  * Inputs:  ct - number of dependents in the list
  110.  *        flist - pointer to a list of pointers to dependent names
  111.  *        pgm_name - name of file whose dependents are being printed
  112.  *        pgmx - extension for pgm_name file (or "" if none)
  113.  *        filex - extension for dependent file names (or "" if none)
  114.  */
  115.     char **flist,*pgm_name,*pgmx,*filex;
  116.     int ct;
  117. {
  118.   int i;
  119.   char buf[LINEMAX], add_name[LINEMAX], pname[LINEMAX];
  120.   
  121.   start_line(file_exten(pgm_name,pgmx,pname),buf);
  122.   if (strcmp(pgm_name,MAINPGM)) strcat(strcat(buf," "),pgm_name);
  123.   for (i = 1; i < ct; i++) {
  124.     file_exten(flist[i],filex,add_name);
  125.     if (columns(buf)+strlen(add_name)+1 >= LINEMAX - 1) {
  126.       fputs(buf,makefile); fputc('\n',makefile);
  127.       start_line(file_exten(pgm_name,pgmx,pname),buf);
  128.     }
  129.     strcat(strcat(buf," "),add_name);
  130.   }
  131.   fputs(buf,makefile); fputc('\n',makefile);
  132.   if (strcmp(pgm_name,MAINPGM)) fprintf(makefile,"\tcc $(OPT) %s\n",pgm_name);
  133.   else { 
  134.     fputs("# ------- construction command goes here ---------",makefile);
  135.     fputc('\n',makefile);
  136.   }
  137. }
  138.  
  139.  
  140. start_line(with_name,buf)
  141. /* 
  142.  * Purpose: give each line a standard indentation 
  143.  * Inputs:  with_name - name of root file on each line
  144.  *        buf - place to put indented line
  145.  */
  146.     char *with_name,*buf;
  147. {
  148.   strcpy(buf,with_name); strcat(buf,"\t");
  149.   if (columns(buf) < 16) strcat(buf,"\t");
  150.   if (columns(buf) < 24) strcat(buf,"\t");
  151.   strcat(buf,":");
  152. }
  153.  
  154. columns(s)
  155. /* 
  156.  * Purpose: count the number of columns a line spans
  157.  * Inputs:  s - the characters in a line
  158.  * Returns: the number of columns (including tab expansion)
  159.  */
  160.     char *s;
  161. {
  162.   int col = 0;
  163.   
  164.   while (*s) {
  165.     if (*s++ == '\t') while (++col & 7);
  166.     else ++col;
  167.   }
  168.   return(col);
  169. }
  170.  
  171. get_dependents(fn,depv,depc)
  172. /* 
  173.  * Purpose: return a list of files depending on a C source file
  174.  * Inputs:  fn - name of the c source file
  175.  * Outputs: depv - list of dependents (an array of pointers to filenames)
  176.  *        depc - number of dependents
  177.  */
  178.      char *fn,***depv;
  179.      int *depc;
  180. {
  181.   char **lst;
  182.   int i;
  183.  
  184.   lst = (char **) malloc(1024*sizeof(char *)); move_name(&lst[0],fn);
  185.   fputs(fn,stdout); fputc('\n',stdout); i = 0;
  186.   
  187.   scan_file(lst,&i,fn); *depv = lst; *depc = i+1;
  188. }
  189.  
  190. move_name(p,s)
  191. /* 
  192.  * Purpose: Allocate space for a new filename and copy it
  193.  * Inputs:  p - location for new pointer to filename
  194.  *        s - pointer to file name
  195.  */
  196.      char **p,*s;
  197. {
  198.   *p = (char *) malloc(strlen(s)+1); strcpy(*p,s);
  199. }
  200.  
  201. scan_file(file_name_list,last_list_used,fn)
  202. /* 
  203.  * Purpose: search a C source file file #includes, and search the #includes
  204.  *        for nested #includes 
  205.  * Inputs:  fn - name of file to scan
  206.  * Outputs: file_name_list - list of included files 
  207.  *        last_list_used - last used filename position in file_name_list
  208.  */
  209.   char **file_name_list, *fn;
  210.   int *last_list_used;
  211. {
  212.   FILE *fp,*fopen();
  213.   char buf[1024],ifn[LINEMAX];
  214.   int j,k;
  215.  
  216.   fp = fopen(fn,"r");
  217.   if (!fp) { fprintf(stdout,"Couldn't open file %s\n",fn); return; }
  218.  
  219.   while (fgets(buf,1024,fp)) {
  220.     if (strncmp(buf,"#include",8) == 0) {
  221.       j = 8;
  222.       while (buf[j] == ' ' || buf[j] == '\t') j++;
  223.       if (buf[j++] != '"') continue;
  224.       k = 0;
  225.       while (buf[j]) {
  226.         if (buf[j] == '"' || buf[j] == '\n') break;
  227.         else ifn[k++] = buf[j++];
  228.       }
  229.       ifn[k] = '\0';
  230.       if (add_name(file_name_list, last_list_used, ifn))
  231.         scan_file(file_name_list, last_list_used, ifn);
  232.     }
  233.   }
  234.   fclose(fp); return;
  235. }
  236.  
  237. add_name(file_name_list, last_list_used, fn)
  238. /* 
  239.  * Purpose: Add a file name to the list if it's not there already
  240.  * Inputs:  file_name_list - pointer to array of pointers to file names
  241.  *        last_list_used - last element in array with a filename
  242.  *        fn - name of file
  243.  * Returns: 1 if file name added, 0 otherwise
  244.  */
  245.   char **file_name_list, *fn;
  246.   int *last_list_used;
  247. {
  248.   int i;
  249.   for (i = 0; i <= *last_list_used; i++)
  250.     if (!strcmp(file_name_list[i],fn)) return(0);
  251.   *last_list_used += 1;
  252.   move_name(&file_name_list[*last_list_used],fn);
  253.   return(1);
  254. }
  255.